#include "UP_I2C.h"
#include "UP_GPIO.h"

//-----------------OLED端口移植----------------
// GND - GND
// VCC - 3.3V
// SCL - PB6 I2C0_SCL
// SDA - PB7 I2C0_SDA
// addr - 0x78


// -----------------------------------------
void I2C_init(uint32_t i2c, uint32_t addr)
{
    /* I2C0可选SCL： PB6_AF4, PB8_AF4 */
    /* I2C0可选SDA： PB7_AF4, PB9_AF4 */
    UP_I2C_PARAMS params = uc_i2c_params_default;
    params.scl_gpio      = PB6,
    params.scl_af        = GPIO_AF_4,
    params.sda_gpio      = PB7,
    params.sda_af        = GPIO_AF_4,

    // I2C1可选SCL： PF1_AF4, PB8_AF4, PH4_AF4
    // I2C1可选SDA： PB3_AF9, PB11_AF4, PC12_AF4, PF0_AF4, PH5_AF4

    // I2C2可选SCL： PA8_AF4, PH7_AF4
    // I2C2可选SDA： PB4_AF9, PC9_AF4, PH8_AF4

    I2C_init_with_params(i2c, addr, &params);
}
void I2C_init_with_params(uint32_t i2c, uint32_t addr, UP_I2C_PARAMS *params)
{
    /* 使能引脚时钟 */
    UP_GPIO_PARAMS gpio_params = {
        .pull_up_down = GPIO_PUPD_NONE,
        .otype        = GPIO_OTYPE_PP};
    /* 配置SCL引脚复用IIC功能*/
    GPIO_Init_AF_with_config(params->scl_gpio, params->scl_af, &gpio_params);
    /* 配置SDA引脚复用IIC功能*/
    GPIO_Init_AF_with_config(params->sda_gpio, params->sda_af, &gpio_params);
    /* 使能IIC时钟 */
    switch (i2c) {
        case I2C0:
            rcu_periph_clock_enable(RCU_I2C0);
            break;
        case I2C1:
            rcu_periph_clock_enable(RCU_I2C1);
            break;
        case I2C2:
            rcu_periph_clock_enable(RCU_I2C2);
            break;
        default:
            break;
    }

    /* 清除IIC原先配置 */
    i2c_deinit(i2c);
    /* 配置IIC时钟 */
    i2c_clock_config(i2c, params->clkspeed, I2C_DTCY_2);
    /* 配置I2C地址 */
    i2c_mode_addr_config(i2c,
                         params->mode,
                         params->addformat,
                         addr);
    /* 使能I2C */
    i2c_enable(i2c);
    /* 使能应答功能 */
    i2c_ack_config(i2c, I2C_ACK_ENABLE);
}

void wait_i2c(uint32_t i2c, uint32_t addr)
{
    /* 等待I2C总线空闲 */
    while (i2c_flag_get(i2c, I2C_FLAG_I2CBSY))
        ;

    /* 发送起始信号到I2C总线 */
    i2c_start_on_bus(i2c);

    /* 等待发送起始信号成功标志位为1 */
    while (!i2c_flag_get(i2c, I2C_FLAG_SBSEND))
        ;

    /* 发送从机地址到I2C总线 */
    i2c_master_addressing(i2c, addr, I2C_TRANSMITTER);

    /* 等待发送从机地址成功标志位为1 */
    while (!i2c_flag_get(i2c, I2C_FLAG_ADDSEND))
        ;
    /* 清除发送从机地址成功标志位 */
    i2c_flag_clear(i2c, I2C_FLAG_ADDSEND);

    /* 等待传输数据缓冲区为空 */
    while (SET != i2c_flag_get(i2c, I2C_FLAG_TBE))
        ;
}

void I2C_write_array(uint32_t i2c, uint32_t addr,
                     uint8_t array[][8], uint8_t len, uint8_t num)
{
    wait_i2c(i2c, addr);

    /* 发送寄存器地址（发送命令） */
    i2c_data_transmit(i2c, 0x40);

    /* 等待字节传输完成位设置完成 */
    while(!i2c_flag_get(i2c, I2C_FLAG_BTC));

    unsigned char n = 0;
    /* 发送数据 */
    for (n = 0; n < len; n++) {
        i2c_data_transmit(i2c, array[n][num]);
        /* 等待传输数据缓冲区为空 */
        while (SET != i2c_flag_get(i2c, I2C_FLAG_TBE))
            ;
    }

    /* 发送停止信号 */
    i2c_stop_on_bus(i2c);
    
    /* 等待直到停止信号发送完成  */
    while(I2C_CTL0(i2c)&0x0200);
}

void I2C_write(uint32_t i2c, uint32_t addr, uint8_t dat, uint8_t mode)
{
    wait_i2c(i2c, addr);
    
    /* 发送寄存器地址（发送命令） */
    if (mode) {
        i2c_data_transmit(i2c, 0x40);
    } else {
        i2c_data_transmit(i2c, 0x00);
    }

    /* 等待字节传输完成位设置完成 */
    while (!i2c_flag_get(i2c, I2C_FLAG_BTC))
        ;

    /* 发送数据 */
    i2c_data_transmit(i2c, dat);

    /* 等待字节传输完成位设置完成 */
    while (!i2c_flag_get(i2c, I2C_FLAG_BTC))
        ;

    /* 向I2C总线发送停止信号 */
    i2c_stop_on_bus(i2c);

    /* 等待直到停止信号发送完成  */
    while (I2C_CTL0(i2c) & 0x0200)
        ;
}